package com.szewec.ps.greenDao.api;

import com.szewec.ps.greenDao.dao.AlbumFile;
import com.szewec.ps.greenDao.dao.AlbumFileDao;
import com.szewec.ps.greenDao.manager.DaoManager;
import com.szewec.ps.model.DBBase;
import com.szewec.ps.util.CommonUtils;
import com.szewec.ps.util.ListUtil;
import com.szewec.ps.util.LogUtil;
import com.szewec.ps.util.PreferincesContext;
import com.szewec.ps.util.SharedPreferencesUtil;
import com.szewec.ps.util.map.MapUtils;

import org.greenrobot.greendao.AbstractDao;
import org.greenrobot.greendao.query.QueryBuilder;

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

/**
 * add by lgh
 * 对数据的增、删、查、改进行统一封装
 *
 * @param <T> model对象
 * @param <K> ID主键
 */
public class BaseManager<T extends DBBase, K> {
    private static final String TAG = "BaseManager";

    //每一页的条数
    public final static int PAGELIMIT = 10;

    //当前是第几页，默认第一页
    private int currentPage = 1;

    private AbstractDao<T, K> mDao;

    /**
     * 构造函数，这里需要传入具体的Dao，下面的具体操作是根据这个传入的dao进行操作数据库的。
     *
     * @param dao
     */
    public BaseManager(AbstractDao dao) {
        this.mDao = dao;
    }

    /**
     * 插入单个对象
     *
     * @param t model对象
     */
    public void insert(T t) {
        Date now = new Date();
        String userId = (String) SharedPreferencesUtil.getData(PreferincesContext.USER_ID,"");
        String userName = (String) SharedPreferencesUtil.getData(PreferincesContext.USER_SHOW_NAME,"");
        String stageId = (String) SharedPreferencesUtil.getData(PreferincesContext.STAGE_ID,"");
        if (t.getSyncStatus() == null || t.getSyncStatus().equals(PreferincesContext.SYNCSTATUS_ADD)){//本地新增
            LogUtil.i(TAG,"insert本地新增");
            if (com.szewec.ps.util.StringUtils.isEmpty(t.getId())){
                t.setId(CommonUtils.generateId());
            }
            t.setSyncStatus(PreferincesContext.SYNCSTATUS_ADD);
            t.setCreateTime(now);
            t.setCreateUserName(userName);
            t.setCreateUserId(userId);
            t.setDesignStageId(stageId);
            if (t.getxCoordinate() == null || t.getyCoordinate() == null){
                //设置坐标
                Double[] coordinates = MapUtils.getCoordinate();
                if (coordinates != null && coordinates.length == 2){
                    t.setxCoordinate(coordinates[0]);
                    t.setyCoordinate(coordinates[1]);
                }
            }
        }else if (t.getSyncStatus().equals(PreferincesContext.SYNCSTATUS_SYNCHRONIZED)){//上传过或从服务端下载的修改
            LogUtil.i(TAG,"上传过或从服务端下载的修改");
            t.setSyncStatus(PreferincesContext.SYNCSTATUS_EDIT);
        }
        mDao.insertOrReplace(t);
    }


    /**
     * 批量插入或更新
     * @param list model对象集合
     */
    public void insertBatch(List<T> list) {
        Date now = new Date();
        String userId = (String) SharedPreferencesUtil.getData(PreferincesContext.USER_ID,"");
        String userName = (String) SharedPreferencesUtil.getData(PreferincesContext.USER_SHOW_NAME,"");
        String stageId = (String) SharedPreferencesUtil.getData(PreferincesContext.STAGE_ID,"");
        //对每一个对象进行赋值
        for (T t : list) {
            if (t.getSyncStatus() == null || t.getSyncStatus().equals(PreferincesContext.SYNCSTATUS_ADD)){//本地新增
                LogUtil.i(TAG,"insertBatch本地新增");
                if (com.szewec.ps.util.StringUtils.isEmpty(t.getId())){
                    t.setId(CommonUtils.generateId());
                }
                t.setSyncStatus(PreferincesContext.SYNCSTATUS_ADD);
                t.setCreateTime(now);
                t.setCreateUserName(userName);
                t.setCreateUserId(userId);
                t.setDesignStageId(stageId);
            }else if (t.getSyncStatus().equals(PreferincesContext.SYNCSTATUS_SYNCHRONIZED)){//上传过或从服务端下载的修改
                LogUtil.i(TAG,"上传过或从服务端下载的修改");
                t.setSyncStatus(PreferincesContext.SYNCSTATUS_EDIT);
            }
        }
        //批量插入
        mDao.insertOrReplaceInTx(list);
    }

    /**
     * 下载用
     * @param list model对象集合
     */
    public void insertBatch4Download(List<T> list) {
        //先清空数据
        mDao.deleteAll();
        if (ListUtil.isNotEmpty(list)){
            //对每一个对象进行赋值
            for (T t : list) {
                t.setSyncStatus(PreferincesContext.SYNCSTATUS_SYNCHRONIZED);
            }
            //批量插入
            mDao.insertOrReplaceInTx(list);
        }
    }

    /**
     * 通过ID删除一个对象
     *
     * @param id 主键
     */
    public void deleteByID(K id) {
        //先根据主键查询对象
        T t = query(id);
        //根据逻辑对该对象进行操作
        delete(t);
    }

    /**
     * 通过传入的对象删除它
     *
     * @param t model对象
     */
    public void delete(T t) {
        if (t.getSyncStatus().equals(PreferincesContext.SYNCSTATUS_ADD)) {
            //如果该条数据是新增的,说明没有同步到云端,可直接删除本地数据
            mDao.delete(t);
        } else {
            //如果该条数据是从云端更新下来的,则把数据状态设置为删除状态,当同步到云端时可让云端识别并进行删除
            t.setSyncStatus(PreferincesContext.SYNCSTATUS_DELETE);
            //更新本地数据，后期同步即可
            mDao.update(t);
        }
        //删除关联的文件
        deleteFile(t.getId());
    }

    /**
     * 删除文件
     */
    public void deleteFile(String relevantId){
        AlbumFileDao albumFileDao = DaoManager.getInstance().getSession().getAlbumFileDao();
        //先查询
        List<AlbumFile> albumFiles = albumFileDao.queryRaw("where RELEVANT_ID = ?",relevantId);
        List<AlbumFile> needDelete = new ArrayList<>();
        if (ListUtil.isNotEmpty(albumFiles)){
            Iterator<AlbumFile> iterator = albumFiles.iterator();
            while (iterator.hasNext()){
                AlbumFile albumFile = iterator.next();
                //本地新增的直接删除
                if (albumFile.getSyncStatus().equals(PreferincesContext.SYNCSTATUS_ADD)){
                    needDelete.add(albumFile);
                    iterator.remove();
                }else {
                    //云端有的标记为删除
                    albumFile.setSyncStatus(PreferincesContext.SYNCSTATUS_DELETE);
                }
            }
        }
        //更新数据库
        if (ListUtil.isNotEmpty(needDelete)){
            albumFileDao.deleteInTx(needDelete);
        }
        if (ListUtil.isNotEmpty(albumFiles)){
            albumFileDao.updateInTx(albumFiles);
        }
    }

    /**
     * 批量删除传入的对象集合
     *
     * @param list model对象集合
     */
    public void delete(List<T> list) {
        for (T t : list) {
            delete(t);
        }
//        mDao.deleteInTx(list);
    }

    /**
     * 请慎重使用！！！！
     * 清空数据
     */
    public void deleteAll() {
        mDao.deleteAll();
    }

    /**
     * 更新一个对象
     *
     * @param t model对象
     */
    public void update(T t) {
        if (t.getSyncStatus().equals(PreferincesContext.SYNCSTATUS_SYNCHRONIZED)) {//如果该条数据是从云端更新下来的,则把数据状态设置为修改状态,当同步到云端时可让云端识别并进行修改
            t.setSyncStatus(PreferincesContext.SYNCSTATUS_EDIT);
        }
        //如果不是则表示该条数据是本地新增的，其状态应该还是SYNCSTATUS_ADD
        mDao.update(t);
    }

    /**
     * 批量更新
     *
     * @param list model对象集合
     */
    public void update(List<T> list) {
        for (T t : list) {
            if (t.getSyncStatus().equals(PreferincesContext.SYNCSTATUS_SYNCHRONIZED)) {//如果该条数据是从云端更新下来的,则把数据状态设置为修改状态,当同步到云端时可让云端识别并进行修改
                t.setSyncStatus(PreferincesContext.SYNCSTATUS_EDIT);
            }
        }
        //批量更新
        mDao.updateInTx(list);
    }

    /**
     * 通过ID查询对象
     *
     * @param id 主键
     * @return model对象
     */
    public T query(K id) {
        return mDao.load(id);
    }

    /**
     * 查询全部数据
     *
     * @return model对象
     */
    public List<T> queryAll() {
        return mDao.loadAll();
    }

    /**
     * 查询不包含删除状态的全部数据
     *
     * @return
     */
    public List<T> queryAllWithoutDeleted() {
        //根据阶段ID过滤
        String stageId = (String) SharedPreferencesUtil.getData(PreferincesContext.STAGE_ID,"");
        return query("where SYNC_STATUS != ? and DESIGN_STAGE_ID = ?", String.valueOf(PreferincesContext.SYNCSTATUS_DELETE),stageId);
    }

    /**
     * 根据业务的surveyId查询不包含删除状态的全部数据
     *
     * @return
     */
    public List<T> queryAllBySurveyId(String surveyId) {
        return query("where SYNC_STATUS != ? and SURVEY_ID = ?", String.valueOf(PreferincesContext.SYNCSTATUS_DELETE), surveyId);
    }

    /**
     * 根据关联id查询不包含删除状态的全部附件
     *
     * @return
     */
    public List<T> queryAlbumFiles(String relevantId) {
        return query("where  SYNC_STATUS != ? and RELEVANT_ID = ?", String.valueOf(PreferincesContext.SYNCSTATUS_DELETE), relevantId);
    }

    /**
     * 根据关联id, bizType查询不包含删除状态的全部附件
     *
     * @return
     */
    public List<T> queryAlbumFiles(String relevantId, String bizType) {
        return query("where SYNC_STATUS != ? and RELEVANT_ID = ? and BIZ_TYPE = ?", String.valueOf(PreferincesContext.SYNCSTATUS_DELETE), relevantId, bizType);
    }

    /**
     * 查询需要上传的全部数据
     *
     * @return
     */
    public List<T> queryUnsyncedData() {
        return query("where SYNC_STATUS in (2,3,4)");
    }

    /**
     * 查询需要上传的全部数据
     *
     * @return
     */
    public List<AlbumFile> queryUnsyncedFileByBizType(List<String> bizIdList) {
        AlbumFileDao albumFileDao = DaoManager.getInstance().getSession().getAlbumFileDao();
        List<Integer> status = new ArrayList<>();
        status.add(2);
        status.add(3);
        status.add(4);
        List<AlbumFile> albumFiles = albumFileDao.queryBuilder().where(AlbumFileDao.Properties.RelevantId.in(bizIdList),AlbumFileDao.Properties.SyncStatus.in(status)).list();
        return albumFiles;
    }

    /**
     * 通过sql语句查询对象
     *
     * @param where
     * @param params
     * @return model对象集合
     */
    public List<T> query(String where, String... params) {
        return mDao.queryRaw(where, params);
    }

    /**
     * 通过queryBuilder的方式查询时需要构造一个QueryBuilder
     *
     * @return QueryBuilder对象
     */
    public QueryBuilder<T> queryBuilder() {
        return mDao.queryBuilder();
    }

    /**
     * 上传完更新同步状态
     * @param list list
     */
    public void updateUploadFinishedSyncStatus(List<T> list) {
        List<T> needDeletedList = new ArrayList<>();
        Iterator<T> iterator = list.iterator();
        while (iterator.hasNext()){
            T t= iterator.next();
            if (!t.getSyncStatus().equals(PreferincesContext.SYNCSTATUS_DELETE)) {
                t.setSyncStatus(PreferincesContext.SYNCSTATUS_SYNCHRONIZED);
            }else {
                needDeletedList.add(t);
                iterator.remove();
            }
        }
        mDao.updateInTx(list);
        if (ListUtil.isNotEmpty(needDeletedList)){
            mDao.deleteInTx(needDeletedList);
        }
    }
    /**
     * 上传完更新同步状态
     */
    public void updateUploadFinishedSyncStatus(T t) {
        if (!t.getSyncStatus().equals(PreferincesContext.SYNCSTATUS_DELETE)) {
            t.setSyncStatus(PreferincesContext.SYNCSTATUS_SYNCHRONIZED);
        }else {
            //删除状态的直接从数据库删除
            mDao.delete(t);
        }
        mDao.update(t);
    }

    /**
     * 查询count
     *
     * @return count
     */
    public long count() {
        return mDao.count();
    }

    /**
     * 刷新缓存，具体没有深入研究，需要后期深入踩坑
     *
     * @param t refresh
     */
    //TODO 深入理解greenDao的缓存机制，一定要利用其缓存机制，提高查询效率
    public void refresh(T t) {
        mDao.refresh(t);
    }

    public AbstractDao<T, K> getmDao() {
        return mDao;
    }

    public int getCurrentPage() {
        return currentPage;
    }

    public void setCurrentPage(int currentPage) {
        this.currentPage = currentPage;
    }
}
